﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using XMLGener.Interfaces;
using XMLGener.Utils;
using XMLGener.Data;
namespace XBasicModules
{
    /// <summary>
    /// Generator of increasing numbers
    /// </summary>
    public class NumberCounter : ModuleBase, XMLGenerModuleInterface
    {

        private decimal actualNumber = 0;
        private int step = 1;
        private bool useMaxBound = false;
        private decimal minBound = 0;
        private decimal maxBound = 0;


        #region XMLGenerModuleInterface Members

        /// <summary>
        /// Generate next number
        /// </summary>
        /// <returns>number</returns>
        public virtual string generate()
        {
            
            String result  = Convert.ToString(actualNumber);
            
            this.actualNumber+=step;
            if (useMaxBound && this.actualNumber > maxBound)
                this.actualNumber = minBound;
            return result;
        }

        /// <summary>
        /// Retrurn definitnion of this module
        /// </summary>
        /// <returns>xml data</returns>
        public virtual string getDefinition()
        {
            return
              "<function>"+
              "   <name>Incremental number</name>"+
              "   <id>incrementNumber</id>"+
              "   <type>long</type>"+
              "   <attributes>"+
              "     <attribute>"+
              "         <name>Starts value</name>"+
              "         <id>startnum</id>"+
              "         <type>number</type>"+
              "      </attribute>"+
              "      <attribute>"+
              "         <name>Step</name>"+
              "         <id>step</id>"+
              "         <type>number</type>"+
              "      </attribute>"+
              "   </attributes>" +
              "   <acceptrestriction>mininclusive</acceptrestriction>" +
              "   <acceptrestriction>minexclusive</acceptrestriction>" +
              "   <acceptrestriction>maxinclusive</acceptrestriction>" +
              "   <acceptrestriction>maxexclusive</acceptrestriction>" +
              "   <acceptrestriction>length</acceptrestriction>" +
              "   <acceptrestriction>minlength</acceptrestriction>" +
              "   <acceptrestriction>maxlength</acceptrestriction>" +
              "</function>"; 
        }

        /// <summary>
        /// Set attributes for this module before generating.
        /// </summary>
        /// <param name="xmlParams"></param>
        /// <param name="parentDocument"></param>
        public virtual void setParameters(string xmlParams, XMLGenerDocument parentDocument)
        {
            if (!this.checkSettingsElement(xmlParams, parentDocument))
                return;
            this.minBound = Convert.ToDecimal(this.getParam("startnum"));
            this.step = Convert.ToInt32(this.getParam("step"));            
            useMaxBound = false;
            if (restrictions != null)
            {
                if (restrictions.useMinInclusive || restrictions.useMinExclusive || restrictions.useMaxInclusive || restrictions.useMaxExclusive)
                {
                    if (restrictions.useMinInclusive && (actualNumber < restrictions.minInclusive))
                    {
                        minBound = restrictions.minInclusive - ((restrictions.minInclusive - actualNumber) % step);
                        if (minBound < restrictions.minInclusive) actualNumber += step;
                    };
                    if (restrictions.useMinExclusive && (actualNumber < restrictions.minExclusive))
                        minBound = restrictions.minExclusive - ((restrictions.minExclusive + 1 - actualNumber) % step) + step;

                    maxBound = minBound;
                    if (restrictions.useMaxExclusive)
                    {
                        useMaxBound = true;
                        maxBound = restrictions.maxExclusive - 1;
                    }
                    if (restrictions.useMaxInclusive)
                    {
                        if (!useMaxBound || maxBound > restrictions.maxInclusive)
                            maxBound = restrictions.maxInclusive;
                        useMaxBound = true;
                    }


                }
                else if (restrictions.useMinLength || restrictions.useMaxLength || restrictions.useLength)
                {
                    decimal minlen = 0;
                    decimal maxlen = 0;
                    if (restrictions.useMinLength)
                        minlen = restrictions.minLength;
                    if (restrictions.useMaxLength)
                    {
                        useMaxBound = true;
                        maxlen = restrictions.maxLength;
                    }
                    if (restrictions.useLength)
                    {
                        useMaxBound = true;
                        minlen = maxlen = restrictions.length;
                    }

                    minBound = Decimal.Floor(Convert.ToDecimal(Math.Pow(10, Convert.ToDouble(minlen - 1))));
                    if (useMaxBound)
                        maxBound = Decimal.Floor(Convert.ToDecimal(Math.Pow(10, Convert.ToDouble(maxlen)) - 1));
                    actualNumber = minBound - (minBound % step);
                    if (actualNumber < minBound) actualNumber += step;
                    minBound = actualNumber;

                }
            }

            actualNumber = minBound;

                
        }

        #endregion
    }
}
